package main

import (
	"encoding/json"
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"raftkv/pkg/consistenthash"
	"strings"
	"sync"
)

type HTTPProxy struct {
	selector *consistenthash.Selector
	sync.RWMutex
	logger *log.Logger
}
func NewHTTPProxy()*HTTPProxy {
	return &HTTPProxy{
		selector: consistenthash.NewSelector(),
		logger: log.New(os.Stderr,"[proxy] ",log.LstdFlags),
	}
}
func(hp *HTTPProxy) ServeHTTP(w http.ResponseWriter, r *http.Request){
	hp.logger.Println("method:",r.URL.Path)

	if strings.HasPrefix(r.URL.Path,"/addProxy"){
		hp.logger.Println("method:",r.Method)
		hp.handleAddRequest(w,r)
	}else if r.URL.Path == "/key" {
		hp.handleProxy(w,r)
	}else{
		w.WriteHeader(http.StatusNotFound)
	}
}

func (hp *HTTPProxy) handleAddRequest(w http.ResponseWriter, r *http.Request) {
	m := map[string]string{}
	if err := json.NewDecoder(r.Body).Decode(&m);err !=nil{
		w.WriteHeader(http.StatusInternalServerError)
	}
	serviceName := m["serviceName"]
	if serviceName==""{
		w.WriteHeader(http.StatusBadRequest)
	}
	ip := m["ip"]
	if ip==""{
		w.WriteHeader(http.StatusBadRequest)
	}
	ip = "http://"+ip
	hp.selector.Add(serviceName,ip)
	hp.logger.Printf("add Service success:%v,ipAddr:",serviceName,ip)

}

func (hp *HTTPProxy) handleProxy(w http.ResponseWriter, r *http.Request) {
	getKey := func()string{
		return ""
	}
	key := getKey()
	ipPort := hp.selector.Select(key)
	urlStr := ipPort + r.URL.Path + "?"+r.URL.RawQuery
	parse, err := url.Parse(urlStr)
	if err ==nil{
		hp.logger.Println("bad url")
	}
	proxy := httputil.NewSingleHostReverseProxy(parse)
	hp.logger.Println("start proxy")
	proxy.ServeHTTP(w,r)
	hp.logger.Println("finish proxy")
}
func main() {
	http.Handle("/",NewHTTPProxy())
	log.Println("proxy start success")
	err := http.ListenAndServe(":3000", nil)
	if err !=nil{
		log.Println("proxy http start err")
	}
}


